package org.bankabeule.ui.views;


import org.bankabeule.Account;
import org.bankabeule.Model;
import org.bankabeule.Operation;
import org.bankabeule.core.ModelManager;
import org.bankabeule.ui.Activator;
import org.bankabeule.ui.actions.AddAccountAction;
import org.bankabeule.ui.editors.AccountEditor;
import org.bankabeule.ui.editors.AccountEditorInput;
import org.bankabeule.ui.utils.Logger;
import org.bankabeule.ui.utils.UIUtils;
import org.bankabeule.ui.wizards.AccountWizard;
import org.bankabeule.util.AccountAdapter;
import org.bankabeule.util.ModelAdapter;
import org.bankabeule.util.Utils;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;


public class AccountsView extends AbstractViewPart {
	

	/**
	 * ID
	 */
	public static final String ID = "org.bankabeule.ui.views.AccountsView";
	
	/**
	 * FormToolkit
	 */
	private FormToolkit tk;
	
	/**
	 * Man pane
	 */
	private ScrolledForm mainComposite;
	
	/**
	 * Model adapter
	 */
	private ModelAdapter modelAdapter;
	
	/**
	 * Account adapter
	 */
	private AccountAdapter accountAdapter;
	
	
	/**
	 * The constructor.
	 */
	public AccountsView() {
		super();
	}

	
	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	public void createPartControl(Composite parent) {		
		setPartName("None");		
		tk = new FormToolkit(parent.getDisplay());
		mainComposite = tk.createScrolledForm(parent);
		mainComposite.getBody().setLayout(new GridLayout(1, true));
		// add actions
		IToolBarManager toolbar = getViewSite().getActionBars().getToolBarManager();
		toolbar.add(new AddAccountAction());
		toolbar.add(new Action("Collapse All", Activator.getImageDescriptor("CollapseAll.gif")) {
			@Override
			public void run() {
				for (Control control : mainComposite.getBody().getChildren()) {
					Section section = (Section) control;
					section.setExpanded(false);
				}
			}
		});
		toolbar.add(new Action("Expand All", Activator.getImageDescriptor("ExpandAll.gif")) {
			@Override
			public void run() {
				for (Control control : mainComposite.getBody().getChildren()) {
					Section section = (Section) control;
					section.setExpanded(true);
				}
			}
		});
		// create adapters
		accountAdapter = new AccountAdapter() {

			@Override
			public void accountChanged(Account account) {
				updateAccountSection(account);
			}
			@Override
			public void operationAdded(Operation operation) {
				Utils.calculateValue((Account) operation.eContainer());
			}
			@Override
			public void operationRemoved(Operation operation, Account account) {
				Utils.calculateValue(account);
			}
		};
		modelAdapter = new ModelAdapter() {

			@Override
			public void accountAdded(Account account) {
				createAccountSection(account);
			}

			@Override
			public void accountRemoved(Account account) {
				destroyAccountSection(account);
			}
			
		};		
	}


	/**
	 * Create an Account section
	 */
	private void createAccountSection(Account account) {
		Section section = tk.createSection(mainComposite.getBody(), 
				Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED);
		section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		section.setText(""+account.getId()+" ("+account.getName()+")");
		section.setToolTipText(account.getDescription());
		section.setData(account);
		Composite sectionComposite = tk.createComposite(section);
		section.setClient(sectionComposite);
		sectionComposite.setLayout(new GridLayout(2, false));
		// add value field
		tk.createLabel(sectionComposite, "Value: ");
		Label valueLabel = tk.createLabel(sectionComposite, String.format("%.2f", account.getValue()));
		valueLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		Font font = JFaceResources.getDefaultFont();
		font.style = SWT.BOLD;
		valueLabel.setFont(font);
		// add hyperlinks
		ImageHyperlink editlink = tk.createImageHyperlink(sectionComposite, SWT.NONE);
		editlink.setImage(Activator.getImageDescriptor("Edit.gif").createImage());
		editlink.setText("Edit properties ...");
		editlink.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 2, 1));
		editlink.setHref(account);
		editlink.addHyperlinkListener(new HyperlinkAdapter() {

			public void linkActivated(HyperlinkEvent e) {
				try {
					WizardDialog dialog = new WizardDialog(Display.getCurrent().getActiveShell(),
							new AccountWizard((Account) e.getHref())){
						@Override
						protected void configureShell(Shell newShell) {
							super.configureShell(newShell);
							UIUtils.center(newShell, getParentShell(), 400, 500);
						}
					};
					dialog.open();
				} catch (Exception ex) {
					Logger.log(ex);
				}
			}
			
		});		
		ImageHyperlink editOplink = tk.createImageHyperlink(sectionComposite, SWT.NONE);
		editOplink.setImage(Activator.getImageDescriptor("Edit.gif").createImage());
		editOplink.setText("Edit operations ...");
		editOplink.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 2, 1));
		editOplink.setHref(account);
		editOplink.addHyperlinkListener(new HyperlinkAdapter() {

			public void linkActivated(HyperlinkEvent e) {
				try {
					getSite().getPage().openEditor(
							new AccountEditorInput((Account) e.getHref()), AccountEditor.ID, true); 
				} catch (Exception ex) {
					Logger.log(ex);
				}
			}
			
		});
		ImageHyperlink remlink = tk.createImageHyperlink(sectionComposite, SWT.NONE);//, SWT.NONE);
		remlink.setImage(Activator.getImageDescriptor("Remove.gif").createImage());
		remlink.setText("Delete account");
		remlink.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 2, 1));
		remlink.setHref(account);
		remlink.addHyperlinkListener(new HyperlinkAdapter() {

			public void linkActivated(HyperlinkEvent e) {
				try {
					boolean mustDelete = MessageDialog.openConfirm(getSite().getShell(), "Confirmation", "Do you really want to delete this account ?");
					if (mustDelete) {
						ModelManager.get().getModel().getAccounts().remove((Account) e.getHref());
					}
				} catch (Exception ex) {
					Logger.log(ex);
				}
			}
			
		});
		mainComposite.layout(true, true);
		account.eAdapters().add(accountAdapter);
	}


	/**
	 * Destroy an Account section
	 */
	private void destroyAccountSection(Account account) {
		IEditorPart editor = getSite().getPage().findEditor(new AccountEditorInput(account));
		if (editor != null) {
			getSite().getPage().closeEditor(editor, false);
		}
		for (Control control : mainComposite.getBody().getChildren()) {
			if (control.getData().equals(account)) {
				control.dispose();	
			}
		}
		mainComposite.layout(true, true);
		account.eAdapters().remove(accountAdapter);
	}


	/**
	 * Update an Account section
	 */
	private void updateAccountSection(Account account) {
		for (Control control : mainComposite.getBody().getChildren()) {
			if (control.getData().equals(account)) {
				Section section = (Section) control;
				section.setText(""+account.getId()+" ("+account.getName()+")");
				section.setToolTipText(account.getDescription());
				Composite sectionComposite = (Composite) section.getChildren()[2];
				Label value = (Label) sectionComposite.getChildren()[1];
				value.setText(String.format("%.2f", account.getValue()));
				section.layout(true, true);
			}
		}
	}
	
	
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		Control[] childrens = mainComposite.getBody().getChildren();
		if (childrens.length > 0) {
			childrens[0].setFocus();
		}
	}

	
	public void modelLoaded(Model model) {
		setPartName(model.eResource().getURI().lastSegment());
		// register adapter
		model.eAdapters().add(modelAdapter);
		// get accounts
		for (Account account : model.getAccounts()) {
			createAccountSection(account);
		}
		mainComposite.layout(true, true);
	}

	
	public void modelUnloaded(Model model) {
		setPartName("None");
		for (Control control : mainComposite.getBody().getChildren()) {
			control.dispose();
		}
	}


	
}